package cn.sunyblog.tool.threadpool;

import cn.sunyblog.tool.threadpool.config.DynamicThreadPoolConfig;
import cn.sunyblog.tool.threadpool.monitor.ThreadPoolMetrics;
import cn.sunyblog.tool.threadpool.strategy.DefaultAdjustmentStrategy;
import cn.sunyblog.tool.threadpool.web.ThreadPoolWebController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 动态线程池监控应用程序主类
 *
 * @author sunyblog
 */
@SpringBootApplication
public class ThreadPoolMonitorApplication {
    private static DynamicThreadPoolExecutor executor;
    private static final AtomicInteger taskCounter = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext context = SpringApplication.run(ThreadPoolMonitorApplication.class, args);

        System.out.println("\n=== 动态线程池Web监控示例启动 ===");
        System.out.println("Web监控界面: http://localhost:8080/threadpool/monitor");
        System.out.println("========================================\n");

        // 创建默认调整策略 - 使用智能扩容算法，确保配置一致性
//        DynamicThreadPoolConfig config = new DynamicThreadPoolConfig(4, 8, 100);
        DynamicThreadPoolConfig config = new DynamicThreadPoolConfig(5, 14, 600);
        DefaultAdjustmentStrategy strategy = new DefaultAdjustmentStrategy(config);
        System.out.println("使用策略: DefaultAdjustmentStrategy (智能扩容算法 - 队列75%触发扩容)");

        // 使用便捷构造函数创建动态线程池 - 测试智能扩容
//        executor = new DynamicThreadPoolExecutor(
//                4,     // 核心线程数 - 小配置测试扩容
//                8,     // 最大线程数 - 小配置测试扩容
//                30,    // 线程存活时间
//                TimeUnit.SECONDS,
//                100,    // 队列容量 - 小配置便于观察扩容
//                strategy,
//                "SmartScalingPool"
//        );

        executor = new DynamicThreadPoolExecutor(
                5,     // 核心线程数 - 小配置测试扩容
                14,     // 最大线程数 - 小配置测试扩容
                30,    // 线程存活时间
                TimeUnit.SECONDS,
                600,    // 队列容量 - 小配置便于观察扩容
                strategy,
                "SmartScalingPool"
        );

        // 注册到Web控制器
        ThreadPoolWebController.registerThreadPool("SmartScalingPool", executor);

        // 启动监控数据收集线程
        startMetricsCollection();

        System.out.println("初始配置: 核心线程数=16, 最大线程数=32, 队列容量=1000");
        System.out.println("智能扩容: 队列使用率75%触发扩容，根据配置类型智能调整");

        // 等待一段时间让用户访问Web界面
        System.out.println("\n请访问 http://localhost:8080/threadpool/monitor 查看监控界面");
        System.out.println("3秒后开始执行测试场景...\n");
        Thread.sleep(3000);

        // 模拟智能扩容测试场景
        simulateSmartScalingScenarios();

        // 保持应用运行以便查看Web界面
        System.out.println("\n=== 测试完成，Web监控界面仍可访问 ===");
        System.out.println("按 Ctrl+C 退出程序");

        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("\n正在关闭线程池...");
            executor.shutdown();
            try {
                if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
            context.close();
            System.out.println("程序已退出");
        }));

        // 等待测试完成后再退出
        // Thread.currentThread().join(); // 移除无限等待
    }

    /**
     * 启动指标收集
     */
    private static void startMetricsCollection() {
        Thread metricsThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    ThreadPoolMetrics metrics = executor.getCurrentMetrics();
                    ThreadPoolWebController.addMetricsHistory("SmartScalingPool", metrics);
                    Thread.sleep(1000); // 每1秒收集一次指标，更频繁的监控
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });
        metricsThread.setDaemon(true);
        metricsThread.start();
    }

    /**
     * 瞬时并发能力测试 - 验证快速响应能力
     */
    private static void simulateSmartScalingScenarios() throws InterruptedException {

        // 初始状态
        System.out.println("\n=== 初始状态 ===");
        printCurrentStatus();
        Thread.sleep(2000);

        // 瞬时并发测试1：小规模突发
        System.out.println("\n=== 瞬时并发测试1：小规模突发 ===");
        submitTasks(300, 200, "小规模突发任务");
        Thread.sleep(2000); // 等待扩容响应
        printCurrentStatus();

        // 瞬时并发测试2：中等规模突发
        System.out.println("\n=== 瞬时并发测试2：中等规模突发 ===");
        submitTasks(800, 200, "中等规模突发任务");
        Thread.sleep(2000); // 等待扩容响应
        printCurrentStatus();

        // 瞬时并发测试3：大规模突发
        System.out.println("\n=== 瞬时并发测试3：大规模突发 ===");
        submitTasks(1500, 200, "大规模突发任务");
        Thread.sleep(3000); // 等待扩容响应
        printCurrentStatus();

        // 极限瞬时并发测试：超大规模突发
        System.out.println("\n=== 极限瞬时并发测试：超大规模突发 ===");
        submitTasks(3000, 200, "超大规模突发任务");
        Thread.sleep(3000); // 等待扩容响应
        printCurrentStatus();

        // 连续瞬时并发测试：模拟流量波峰
        System.out.println("\n=== 连续瞬时并发测试：流量波峰 ===");
        for (int wave = 1; wave <= 3; wave++) {
            System.out.println(String.format("\n--- 第%d波并发冲击 ---", wave));
            submitTasks(1000, 200, String.format("第%d波冲击任务", wave));
            Thread.sleep(1000); // 短暂间隔
            printCurrentStatus();
        }

        // 等待任务完成，观察缩容
        System.out.println("\n=== 等待任务完成，观察缩容 ===");
        Thread.sleep(10000); // 等待任务完成
        printCurrentStatus();
        
        Thread.sleep(10000); // 继续等待缩容
        printCurrentStatus();

        System.out.println("\n=== 瞬时并发能力测试完成 ===");
        System.out.println("总瞬时并发检测次数: " + 
            ((DefaultAdjustmentStrategy)executor.getAdjustmentStrategy()).burstDetectionCount);
    }

    /**
     * 并发任务提交方法 - 模拟真实瞬时并发场景
     */
    private static void submitTasks(int taskCount, long taskDurationMs, String taskType) {
        System.out.println(String.format("并发提交 %d 个任务，每个任务耗时 %dms", taskCount, taskDurationMs));

        AtomicInteger rejectedCount = new AtomicInteger(0);
        AtomicInteger successCount = new AtomicInteger(0);
        CountDownLatch submitLatch = new CountDownLatch(taskCount);
        
        // 使用线程池并发提交任务，模拟瞬时并发
        ExecutorService submitExecutor = Executors.newFixedThreadPool(Math.min(50, taskCount));
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < taskCount; i++) {
            final int taskId = taskCounter.incrementAndGet();
            submitExecutor.submit(() -> {
                try {
                    executor.execute(() -> {
                        try {
                            Thread.sleep(200); // 固定任务执行时间
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    });
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    rejectedCount.incrementAndGet();
                    System.out.println(String.format("[%s-%d] 被拒绝: %s", taskType, taskId, e.getMessage()));
                } finally {
                    submitLatch.countDown();
                }
            });
        }
        
        try {
            submitLatch.await(10, TimeUnit.SECONDS); // 等待所有提交完成
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        submitExecutor.shutdown();
        
        long submitTime = System.currentTimeMillis() - startTime;
        double submitRate = taskCount * 1000.0 / submitTime;
        
        System.out.println(String.format("提交结果: 成功 %d 个, 被拒绝 %d 个, 提交耗时 %dms, 提交速率 %.1f 任务/秒", 
            successCount.get(), rejectedCount.get(), submitTime, submitRate));

        // 记录调整历史
        if (rejectedCount.get() > 0) {
            ThreadPoolWebController.addAdjustmentHistory("SmartScalingPool",
                    String.format("%s: %d个任务被拒绝，提交速率%.1f任务/秒", taskType, rejectedCount.get(), submitRate));
        }
    }


    /**
     * 打印当前状态
     */
    private static void printCurrentStatus() {
        ThreadPoolMetrics metrics = executor.getCurrentMetrics();
        System.out.println("\n=== 当前线程池状态 ===");
        System.out.println(metrics.toString());
        System.out.println(executor.getAdjustmentStats());
        System.out.println("========================\n");

        // 添加到Web历史记录
        ThreadPoolWebController.addAdjustmentHistory("SmartScalingPool",
                String.format("状态检查: 核心=%d, 最大=%d, 活跃=%d, 队列=%d, 负载等级=%d",
                        metrics.getCorePoolSize(), metrics.getMaximumPoolSize(), metrics.getActiveThreads(),
                        metrics.getQueueSize(), metrics.getLoadLevel()));
    }
}